package patterns.creational.builder;

import java.util.ArrayList;
import java.util.List;

/**
 * 建造者模式示例
 * 将一个复杂对象的构建与它的表示分离，使得同样的构建过程可以创建不同的表示
 */
public class BuilderPattern {

    public static void main(String[] args) {
        // 使用传统建造者模式
        System.out.println("===== 传统建造者模式 =====");
        Director director = new Director();
        
        ComputerBuilder gamingBuilder = new GamingComputerBuilder();
        director.constructGamingComputer(gamingBuilder);
        Computer gamingComputer = gamingBuilder.getResult();
        System.out.println(gamingComputer);
        
        ComputerBuilder officeBuilder = new OfficeComputerBuilder();
        director.constructOfficeComputer(officeBuilder);
        Computer officeComputer = officeBuilder.getResult();
        System.out.println(officeComputer);
        
        // 使用链式调用的建造者模式
        System.out.println("\n===== 链式调用建造者模式 =====");
        House house1 = new House.Builder()
                .buildWalls("砖墙")
                .buildRoof("瓦片屋顶")
                .buildDoors(2)
                .buildWindows(6)
                .buildGarage(true)
                .buildSwimmingPool(false)
                .build();
        System.out.println(house1);
        
        House house2 = new House.Builder()
                .buildWalls("木墙")
                .buildRoof("平顶")
                .buildDoors(3)
                .buildWindows(8)
                .buildGarage(true)
                .buildSwimmingPool(true)
                .build();
        System.out.println(house2);
    }
}

/**
 * 传统建造者模式实现
 */
class Computer {
    private String cpu;
    private String ram;
    private String storage;
    private String gpu;
    private String motherboard;
    private String powerSupply;
    private List<String> peripherals = new ArrayList<>();
    
    public void setCpu(String cpu) {
        this.cpu = cpu;
    }
    
    public void setRam(String ram) {
        this.ram = ram;
    }
    
    public void setStorage(String storage) {
        this.storage = storage;
    }
    
    public void setGpu(String gpu) {
        this.gpu = gpu;
    }
    
    public void setMotherboard(String motherboard) {
        this.motherboard = motherboard;
    }
    
    public void setPowerSupply(String powerSupply) {
        this.powerSupply = powerSupply;
    }
    
    public void addPeripheral(String peripheral) {
        peripherals.add(peripheral);
    }
    
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Computer Specifications:\n");
        sb.append("- CPU: ").append(cpu).append("\n");
        sb.append("- RAM: ").append(ram).append("\n");
        sb.append("- Storage: ").append(storage).append("\n");
        sb.append("- GPU: ").append(gpu).append("\n");
        sb.append("- Motherboard: ").append(motherboard).append("\n");
        sb.append("- Power Supply: ").append(powerSupply).append("\n");
        sb.append("- Peripherals: ").append(String.join(", ", peripherals));
        return sb.toString();
    }
}

interface ComputerBuilder {
    void buildCpu();
    void buildRam();
    void buildStorage();
    void buildGpu();
    void buildMotherboard();
    void buildPowerSupply();
    void buildPeripherals();
    Computer getResult();
}

class GamingComputerBuilder implements ComputerBuilder {
    private Computer computer = new Computer();
    
    @Override
    public void buildCpu() {
        computer.setCpu("Intel Core i9-12900K");
    }
    
    @Override
    public void buildRam() {
        computer.setRam("32GB DDR5 5200MHz");
    }
    
    @Override
    public void buildStorage() {
        computer.setStorage("2TB NVMe SSD");
    }
    
    @Override
    public void buildGpu() {
        computer.setGpu("NVIDIA RTX 4090");
    }
    
    @Override
    public void buildMotherboard() {
        computer.setMotherboard("ASUS ROG Maximus Z690");
    }
    
    @Override
    public void buildPowerSupply() {
        computer.setPowerSupply("1000W 80+ Platinum");
    }
    
    @Override
    public void buildPeripherals() {
        computer.addPeripheral("机械键盘");
        computer.addPeripheral("游戏鼠标");
        computer.addPeripheral("240Hz显示器");
        computer.addPeripheral("7.1声道耳机");
    }
    
    @Override
    public Computer getResult() {
        return computer;
    }
}

class OfficeComputerBuilder implements ComputerBuilder {
    private Computer computer = new Computer();
    
    @Override
    public void buildCpu() {
        computer.setCpu("Intel Core i5-12400");
    }
    
    @Override
    public void buildRam() {
        computer.setRam("16GB DDR4 3200MHz");
    }
    
    @Override
    public void buildStorage() {
        computer.setStorage("512GB SATA SSD");
    }
    
    @Override
    public void buildGpu() {
        computer.setGpu("Intel UHD Graphics 730");
    }
    
    @Override
    public void buildMotherboard() {
        computer.setMotherboard("ASUS Prime B660M-A");
    }
    
    @Override
    public void buildPowerSupply() {
        computer.setPowerSupply("500W 80+ Bronze");
    }
    
    @Override
    public void buildPeripherals() {
        computer.addPeripheral("标准键盘");
        computer.addPeripheral("光电鼠标");
        computer.addPeripheral("24英寸显示器");
    }
    
    @Override
    public Computer getResult() {
        return computer;
    }
}

class Director {
    public void constructGamingComputer(ComputerBuilder builder) {
        builder.buildCpu();
        builder.buildRam();
        builder.buildStorage();
        builder.buildGpu();
        builder.buildMotherboard();
        builder.buildPowerSupply();
        builder.buildPeripherals();
    }
    
    public void constructOfficeComputer(ComputerBuilder builder) {
        builder.buildCpu();
        builder.buildRam();
        builder.buildStorage();
        builder.buildGpu();
        builder.buildMotherboard();
        builder.buildPowerSupply();
        builder.buildPeripherals();
    }
}

/**
 * 链式调用建造者模式实现
 */
class House {
    private final String walls;
    private final String roof;
    private final int doors;
    private final int windows;
    private final boolean hasGarage;
    private final boolean hasSwimmingPool;
    
    private House(Builder builder) {
        this.walls = builder.walls;
        this.roof = builder.roof;
        this.doors = builder.doors;
        this.windows = builder.windows;
        this.hasGarage = builder.hasGarage;
        this.hasSwimmingPool = builder.hasSwimmingPool;
    }
    
    @Override
    public String toString() {
        return "House{" +
                "walls='" + walls + '\'' +
                ", roof='" + roof + '\'' +
                ", doors=" + doors +
                ", windows=" + windows +
                ", hasGarage=" + hasGarage +
                ", hasSwimmingPool=" + hasSwimmingPool +
                '}';
    }
    
    public static class Builder {
        private String walls;
        private String roof;
        private int doors;
        private int windows;
        private boolean hasGarage;
        private boolean hasSwimmingPool;
        
        public Builder buildWalls(String walls) {
            this.walls = walls;
            return this;
        }
        
        public Builder buildRoof(String roof) {
            this.roof = roof;
            return this;
        }
        
        public Builder buildDoors(int doors) {
            this.doors = doors;
            return this;
        }
        
        public Builder buildWindows(int windows) {
            this.windows = windows;
            return this;
        }
        
        public Builder buildGarage(boolean hasGarage) {
            this.hasGarage = hasGarage;
            return this;
        }
        
        public Builder buildSwimmingPool(boolean hasSwimmingPool) {
            this.hasSwimmingPool = hasSwimmingPool;
            return this;
        }
        
        public House build() {
            return new House(this);
        }
    }
} 